package com.hombio.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Query;


import org.codehaus.jettison.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hombio.UIBean.MedicineTakeItem;
import com.hombio.UIBean.MedicineTakeUI;
import com.hombio.UIBean.Putaway;
import com.hombio.UIBean.Storage;
import com.hombio.UIBean.StorageItem;
import com.hombio.UIBean.StoragePrice;
import com.hombio.UIBean.Take;

import cn.edu.scau.cmi.hombio.dao.EmployeeDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineDAO;
import cn.edu.scau.cmi.hombio.dao.MedicinePriceDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineStorageDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineStorageDetailDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineSupplierDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineTakeDAO;
import cn.edu.scau.cmi.hombio.dao.MedicineTakeDetailDAO;
import cn.edu.scau.cmi.hombio.dao.SupplierDAO;
import cn.edu.scau.cmi.hombio.dao.TaskDAO;
import cn.edu.scau.cmi.hombio.dao.TaskStatusTypeDAO;
import cn.edu.scau.cmi.hombio.domain.CureTaskCourse;
import cn.edu.scau.cmi.hombio.domain.CureTaskMedicine;
import cn.edu.scau.cmi.hombio.domain.CureTaskMethod;
import cn.edu.scau.cmi.hombio.domain.Employee;
import cn.edu.scau.cmi.hombio.domain.Medicine;
import cn.edu.scau.cmi.hombio.domain.MedicinePrice;
import cn.edu.scau.cmi.hombio.domain.MedicineStorage;
import cn.edu.scau.cmi.hombio.domain.MedicineStorageDetail;
import cn.edu.scau.cmi.hombio.domain.MedicineSupplier;
import cn.edu.scau.cmi.hombio.domain.MedicineTake;
import cn.edu.scau.cmi.hombio.domain.MedicineTakeDetail;
import cn.edu.scau.cmi.hombio.domain.PreventionType;
import cn.edu.scau.cmi.hombio.domain.RoleEmployee;
import cn.edu.scau.cmi.hombio.domain.Supplier;
import cn.edu.scau.cmi.hombio.domain.Task;
import cn.edu.scau.cmi.hombio.domain.TaskEmployee;
import cn.edu.scau.cmi.hombio.domain.TaskPrevention;
import cn.edu.scau.cmi.hombio.domain.TaskStatusType;

@Transactional
@Service
public class MedicineMSService {
	@Autowired
	TaskDAO taskDAO;
	@Autowired
	EmployeeDAO employeeDAO;
	@Autowired
	MedicineStorageDetailDAO medicineStorageDetailDAO;
	@Autowired
	MedicineDAO medicineDAO;
	@Autowired
	MedicineSupplierDAO medicineSupplierDAO;
	@Autowired
	SupplierDAO supplierDAO;
	@Autowired
	MedicineStorageDAO medicineStorageDAO;
	@Autowired
	MedicinePriceDAO medicinePriceDAO;
	@Autowired
	MedicineTakeDAO medicineTakeDAO;
	@Autowired
	MedicineTakeDetailDAO medicineTakeDetailDAO;
	@Autowired
	TaskStatusTypeDAO taskStatusTypeDAO;
	@Transactional
	public Employee login(String tel, String pwd){
		
		for(Employee e : employeeDAO.findEmployeeByNumber(tel)){
			
			if(e.getPassword().contentEquals(pwd)){
				return e;
			}
			
		}
		return null;
	}
	
	@Transactional
	public void addMedicine(Medicine medicine){
		for(Medicine m : medicineDAO.findMedicineByNumber(medicine.getNumber())){
			if(m.getName().equals(medicine.getName())){
				return ;
			}
		}
		medicineDAO.store(medicine);
	}
	
	@Transactional
	public void addSupplier(Supplier supplier){
		if(supplierDAO.findSupplierByName(supplier.getName()).size() == 0){
			supplierDAO.store(supplier);
		}
	}
	
	@Transactional
	public void batchDeleteMedicine(String ids){
		String idArray[] = ids.split(",");
		for(String id : idArray){
			Medicine medicine = medicineDAO.findMedicineById(Integer.valueOf(id));
			//只有你无牵无挂，我才能把你杀了
			if(medicine.getPreventionTypesForMedicineId().size()==0
					&&medicine.getCureTaskMedicines().size()==0 
					&&medicine.getCureMedicines().size()==0
					&&medicine.getMedicineStorageDetails().size()==0
					&&medicine.getMedicineSuppliers().size()==0
					&&medicine.getMedicineTakeDetails().size()==0
					&&medicine.getPreventionTypesForMedicineId().size()==0
					&&medicine.getPreventionTypesForReportMedicineId().size() == 0){
				medicineDAO.remove(medicine);
			}
		}
	}
	
	@Transactional
	public void batchDeleteSuppliers(String ids){
		String[] idArray = ids.split(",");
		for(String id : idArray){
			
			Supplier supplier = supplierDAO.findSupplierByPrimaryKey(Integer.valueOf(id));
			if(supplier.getMedicineStorages().size()==0 && supplier.getMedicineSuppliers().size()==0){
				supplierDAO.remove(supplier);
			}
		}
	}
	@Transactional
	public void editPassword(Integer employeeId,String password){
		Employee employee = employeeDAO.findEmployeeById(employeeId);
		employee.setPassword(password);
		employeeDAO.store(employee);
	}
	@SuppressWarnings("unchecked")
	@Transactional
	public List<MedicineTakeUI> getTaskMedicineByEmployeeId(Integer employeeId){
		Query query = taskDAO.createQuery("from Task where taskStatusId<3 and ? between startTime and endTime and memo!='处方审核' and (taskTypeId=2 or taskTypeId=4)", -1, -1);
		query.setParameter(1, Calendar.getInstance());
		List<Task> tasks = query.getResultList();
		List<Task> tasks1 = new ArrayList<Task>();
		for(Task task : tasks){
			for(TaskEmployee te : task.getTaskEmployees()){
				if(te.getEmployee().getId().equals(employeeId)){
					tasks1.add(task);
					break;
				}
			}
		}
		List<MedicineTakeUI> tmList = new ArrayList<MedicineTakeUI>();
		for(Task task : tasks1){
			MedicineTakeUI tm = new MedicineTakeUI();
			tm.setTaskId(task.getId());
			tm.setTaskType(task.getTaskType().getName());
			int count=0;
			List<MedicineTakeItem> medicineItems = new ArrayList<MedicineTakeItem>();
			for(CureTaskCourse ctc : task.getCureTaskCourses()){
				for(CureTaskMethod ctm : ctc.getCureTaskMethods()){
					for(CureTaskMedicine c : ctm.getCureTaskMedicines()){
						MedicineTakeItem medicineItem = new MedicineTakeItem();
						medicineItem.setQuantity(c.getQuantity().intValue());
						medicineItem.setUnit(c.getUnit().getName());
						medicineItem.setName(c.getMedicine().getName());
						medicineItem.setNumber(c.getMedicine().getNumber());
						medicineItem.setTakeQuantity(getTaskMedicineTakeNum(task.getId(), c.getMedicine().getId()));
						if(medicineItem.getTakeQuantity().intValue() >= medicineItem.getQuantity().intValue()){
							count++;
						}
						medicineItems.add(medicineItem);
					}
				}
			}
			
			for(TaskPrevention tp : task.getTaskPreventions()){
				PreventionType pt = tp.getPreventionType();
				MedicineTakeItem medicineItem = new MedicineTakeItem();
				medicineItem.setQuantity(pt.getQuality().intValue());
				medicineItem.setUnit(pt.getUnitByUnitId().getName());
				medicineItem.setName(pt.getMedicineByMedicineId().getName());
				medicineItem.setNumber(pt.getMedicineByMedicineId().getNumber());
				medicineItem.setTakeQuantity(getTaskMedicineTakeNum(task.getId(), pt.getMedicineByMedicineId().getId()));
				medicineItems.add(medicineItem);
			}

			tm.setMedicineItems(medicineItems);
			//去掉已经领完药品的任务，设置为已完成状态
			if(count != medicineItems.size()){
				tmList.add(tm);				
			}else{
				TaskStatusType tst = taskStatusTypeDAO.findTaskStatusTypeById(3);
				task.setTaskStatusType(tst);
				taskDAO.store(task);
			}
		}
		return tmList;
	}
	
	//获取到指定任务领取了指定药品的数量'
	@Transactional
	@SuppressWarnings("unchecked")
	private int getTaskMedicineTakeNum(int taskId, int medicineId){
		//查询已领取数量
		int count = 0;
		Query q = medicineTakeDAO.createQuery("from MedicineTake where taskId = ?", -1, -1);
		q.setParameter(1, taskId);
		for(MedicineTake mt : (List<MedicineTake>)q.getResultList()){
			for(MedicineTakeDetail mtd : mt.getMedicineTakeDetails()){
				if(mtd.getMedicine().getId() == medicineId){
					count ++;
				}
			}
		}
		return count;
	}
	

	
	
	
	@Transactional
	public List<Employee> getCureOrPreventionEmployees(){
		List<Employee> employees = new ArrayList<Employee>();
		for(Employee employee : employeeDAO.findEmployeeByLogOn(true)){
			employees.add(employee);
		}
		return employees;
	}
	//201707230000500038190166，清肺止咳散，兽药字190585157，兴达药业，020-61950666
	
	/*
	 * 入库时扫描追溯码后对其处理
	 * 若已入库：返回空jsonObject字符串
	 * 否则
	 * 若药品库不存在该药品，先加入药品库
	 * 返回追溯码及关联的药品库中的信息
	 */
	@Transactional
	public StorageItem processTraceCode(String traceCode, Integer supplierId){
		
		StorageItem storage = new StorageItem();
		if(traceCode==null || traceCode.length()<24){
			storage.setTraceCode("-1");
			return storage;
		}
		//1. 检查是否已入库
		String code24 = traceCode.substring(0, 24);
		Set<MedicineStorageDetail> detail = medicineStorageDetailDAO.findMedicineStorageDetailByTraceCode(code24);
		if(detail.size() != 0){
			storage.setTraceCode("0");
			return storage;
		}
		
		String[] str = traceCode.split("，");
		
		//处理一般形式的药品追溯码，实际存在一些特殊形式，需另外处理
		if(str.length == 5){
			String code = str[0];
			String name = str[1];
			//只保留数字
			String number = str[2].replaceAll("\\D", "");
			String company = str[3];
			String phone = str[4];
			storage.setMedicineName(name);
			storage.setTraceCode(code);
			// 检查药品库是否存在该药品
			Set<Medicine> medicineSet = medicineDAO.findMedicineByNumberContaining(number);
			if(medicineSet.size() == 0){
				Medicine medicine = new Medicine();
				medicine.setName(name);
				medicine.setNumber(number);
				medicine.setCompany(company);
				medicine.setPhone(phone);
				Medicine storedMedicine = medicineDAO.store(medicine);
				storage.setMedicineId(storedMedicine.getId());
			}else{
				for(Medicine medicine : medicineSet){					
					storage.setMedicineId(medicine.getId());
				}
			}
			
		}else{
			//特殊形式的追溯码
			String ss = traceCode.replaceAll("\\D", "").substring(24);
			for(Medicine medicine : medicineDAO.findAllMedicines()){
				if(ss.indexOf(medicine.getNumber())!=-1){
					storage.setMedicineId(medicine.getId());
					storage.setMedicineName(medicine.getName());
					storage.setTraceCode(traceCode.substring(0, 24));
					break;
				}
			}
			if(storage.getMedicineId() == null){
				storage.setTraceCode("-1");
			}
		}
		return storage;
	}
	
	
	@Transactional
	public Putaway checkCaseTraceCode(String traceCode1){
		String traceCode = traceCode1.substring(0,24);
		Putaway putaway = new Putaway();
		Set<MedicineStorageDetail> detail = medicineStorageDetailDAO.findMedicineStorageDetailByTraceCode(traceCode);
		if(detail.size() == 0){
			putaway.setCaseTraceCode("0");
		}
		for(MedicineStorageDetail msd : detail){
			putaway.setMedicineId(msd.getMedicine().getId());
			putaway.setMedicineName(msd.getMedicine().getName());
			putaway.setCaseTraceCode(msd.getTraceCode());
		}
		return putaway;
	}
	
	@Transactional
	public Putaway checkBoxTraceCode(String traceCode){
		Putaway putaway = new Putaway();
		Set<MedicineTakeDetail> detail = medicineTakeDetailDAO.findMedicineTakeDetailByBoxTraceCode(traceCode);
		if(detail.size() != 0){
			putaway.setCaseTraceCode("1");
			return putaway;
		}else{
			putaway.setCaseTraceCode("0");
			return putaway;
		}
		
	}
	
	//保存入库记录
	//1.基本记录
	//2.本次入库药品的单价
	@Transactional
	public void saveStorageRecord(Integer employeeId,Integer supplierId, Storage storage){
		Employee employee = employeeDAO.findEmployeeById(employeeId);
		Supplier supplier = supplierDAO.findSupplierById(supplierId);
		MedicineStorage medicineStorage = new MedicineStorage();
		medicineStorage.setEmployee(employee);
		medicineStorage.setSupplier(supplier);
		medicineStorage.setTime(Calendar.getInstance());
		MedicineStorage ms = medicineStorageDAO.store(medicineStorage);
		
		for(StorageItem storageItem : storage.getStorageItems()){
			//medicinePrice.put(storage.getMedicineId(), storage.getPrice());
			MedicineStorageDetail medicineStorageDetail = new MedicineStorageDetail();
			medicineStorageDetail.setIsPutaway(0);
			medicineStorageDetail.setIsUseout(0);
			medicineStorageDetail.setMedicine(medicineDAO.findMedicineById(storageItem.getMedicineId()));
			medicineStorageDetail.setMedicineStorage(ms);
			medicineStorageDetail.setTraceCode(storageItem.getTraceCode());
			medicineStorageDetailDAO.store(medicineStorageDetail);
		}
		
		for(StoragePrice sp : storage.getStoragePrices()){
			
			MedicineSupplier medicineSupplier = null;
			Medicine medicine = medicineDAO.findMedicineById(sp.getMedicineId());
			Query query = medicineSupplierDAO.createQuery("from MedicineSupplier where medicine=? and supplier=?",-1,-1);
			query.setParameter(1, medicine);
			query.setParameter(2, supplier);
			@SuppressWarnings("unchecked")
			List<MedicineSupplier> medicineSuppliers = query.getResultList();
			if(medicineSuppliers.size() != 0){
				for(MedicineSupplier md : medicineSuppliers){
					medicineSupplier = md;
				}
			}else{
				MedicineSupplier ms1 = new MedicineSupplier();
				ms1.setSupplier(supplier);
				ms1.setMedicine(medicine);
				medicineSupplier = medicineSupplierDAO.store(ms1);
			}
			MedicinePrice mp = new MedicinePrice();
			mp.setMedicineStorage(ms);
			mp.setMedicineSupplier(medicineSupplier);
			mp.setPrice(new BigDecimal(sp.getPrice()));
			medicinePriceDAO.store(mp);
		}
	}
	
	@Transactional
	public void savePutawayRecord(Integer employeeId, Putaway[] records){
		Employee employee = employeeDAO.findEmployeeById(employeeId);
		MedicineTake medicineTake = new MedicineTake();
		medicineTake.setEmployeeByPharmacistId(employee);
		medicineTake.setTime(Calendar.getInstance());
		medicineTake.setMemo("上架");
		medicineTakeDAO.store(medicineTake);
		for(Putaway putaway : records){

			Medicine medicine = medicineDAO.findMedicineById(putaway.getMedicineId());
			for(String boxTraceCode : putaway.getBoxTraceCodes()){
				MedicineTakeDetail mtd = new MedicineTakeDetail();
				mtd.setBoxTraceCode(boxTraceCode);
				mtd.setCaseTraceCode(putaway.getCaseTraceCode());
				mtd.setMedicine(medicine);
				//mtd.setMedicineTake(mt);
				medicineTakeDetailDAO.store(mtd);
			}
		}
		
	}
	
	//检查入库的箱子已经被整箱领取
	private boolean isCaseTaken(String caseTraceCode){
		Query q = medicineTakeDetailDAO.createQuery("from MedicineTakeDetail where caseTraceCode = ? and boxTraceCode is null", -1, -1);
		q.setParameter(1, caseTraceCode);
		return q.getResultList().size() == 0 ? false : true;
	}
	
	@Transactional
	public Take isStorage(String caseTraceCode){
		Take take = new Take();
		for(MedicineStorageDetail msd : medicineStorageDetailDAO.findMedicineStorageDetailByTraceCode(caseTraceCode)){
			if(isCaseTaken(caseTraceCode)){
				//已经被领取
				take.setCaseTraceCode("0");
			}else{
				take.setCaseTraceCode(msd.getTraceCode());
				take.setMedicineId(msd.getMedicine().getId());
				take.setMedicineName(msd.getMedicine().getName());
				take.setMedicineNumber(msd.getMedicine().getNumber());
			}
			break;
		}
		return take;
	}
	@Transactional
	public Take isPutaway(String boxTraceCode){
		Take take = new Take();
		for(MedicineTakeDetail mtd : medicineTakeDetailDAO.findMedicineTakeDetailByBoxTraceCode(boxTraceCode)){
			//药品已上架，未被领取
			if(mtd.getMedicineTake() == null){
				take.setBoxTraceCode(mtd.getBoxTraceCode());
				take.setMedicineId(mtd.getMedicine().getId());
				take.setMedicineName(mtd.getMedicine().getName());
				take.setMedicineNumber(mtd.getMedicine().getNumber());
			}else{
				take.setMedicineId(0);
			}
		}
		return take;
	}
	@Transactional
	public void saveTakeRecords(Integer managerId, Integer takerId,Integer taskId,Take[] records){
		
		Employee manager = employeeDAO.findEmployeeById(managerId);
		Employee taker = employeeDAO.findEmployeeById(takerId);
		Task task = taskDAO.findTaskById(taskId);
		
		MedicineTake medicineTake = new MedicineTake();
		medicineTake.setEmployeeByPharmacistId(manager);
		medicineTake.setEmployeeByTakerId(taker);
		medicineTake.setTime(Calendar.getInstance());
		medicineTake.setTask(task);
		MedicineTake mt = medicineTakeDAO.store(medicineTake);
		
		for(Take take : records){
			MedicineTakeDetail mtd = null;
			
			if(take.getCaseTraceCode() == null){
				//已上架
				for(MedicineTakeDetail m : medicineTakeDetailDAO.findMedicineTakeDetailByBoxTraceCode(take.getBoxTraceCode())){
					mtd = m;
				}
			}else{
				//未上架
				mtd = new MedicineTakeDetail();
				mtd.setBoxTraceCode(take.getBoxTraceCode());
				mtd.setCaseTraceCode(take.getCaseTraceCode());	
				mtd.setMedicine(medicineDAO.findMedicineById(take.getMedicineId()));
			}
			mtd.setMedicineTake(mt);
			medicineTakeDetailDAO.store(mtd);
			
		}
		
	}
}
